#pragma once
#include <iostream>
#include <unistd.h>
#include <cassert>
#include <sys/epoll.h>
#include <stdio.h>
#include "data.hpp"
#include "pthreadpool.hpp"
using namespace std;
#define BUFFER_NUM 1024
class Funtion
{
public:
  Funtion() = default;
  void Accept(int sock, unordered_map<int, Data<std::string> *> &map)
  {
    auto cur = map.find(sock);
    assert(cur != map.end());
    cur->second->_ptr = &_pool;
    Add(cur, map);
  }
  void Recv(int sock, unordered_map<int, Data<std::string> *> &map, int listensock)
  {
    auto cur = map.find(sock);
    assert(cur != map.end());
    if (cur->first == listensock)
    {
      Accept(cur->first, map);
      return;
    }
    while (true)
    {
      char buffer[BUFFER_NUM];
      memset(buffer, 0, BUFFER_NUM);
      ssize_t s = recv(cur->first, buffer, BUFFER_NUM - 1, 0);
      if (s > 0)
      {
        cur->second->_inbuffer += buffer;
      }
      else if (s == 0)
      {
        cur->second->_eptr->Epoll_ctl(EPOLL_CTL_DEL, cur->first, 0);
        map.erase(cur->first);
        delete cur->second;
        close(cur->first);
        cout << "已退出" << endl;
        break;
      }
      else
      {
        if (errno == EWOULDBLOCK || errno == EAGAIN)
        {
          cout << "没数据..." << endl;
          _pool.push(cur->second->_inbuffer,cur->second);
          cur->second->_inbuffer.clear();
          break;
        }
        else if (errno == EINTR)
        {
          cout << "被中断，再试一次..." << endl;
          continue;
        }
        else
        {
          cout << "读取错误..." << endl;
          break;
        }
      }
    }
  }
  void Write(int sock, unordered_map<int, Data<std::string> *> &map)
  {
    auto cur = map.find(sock);
    assert(cur != map.end());
    while (true)
    {
      ssize_t s = send(sock, cur->second->_outbuffer.c_str(), cur->second->_outbuffer.size(), 0);
      if (s > 0)
      {
        cout << "发送成功" << endl;
        cur->second->_outbuffer.erase(cur->second->_outbuffer.begin(),cur->second->_outbuffer.begin() + s);
      }
      else
      {
        if (errno == EWOULDBLOCK || errno == EAGAIN)
        {
          cur->second->_eptr->Epoll_ctl(EPOLL_CTL_MOD,cur->first,EPOLLIN | EPOLLET);
          cout << "缓冲区已满，请稍等..." << endl;
          break;
        }
        else if (errno == EINTR)
        {
          cout << "被中断..." << endl;
          continue;
        }
        else
        {
          cout << "send fail :" << strerror(errno) << endl;
          break;
        }
      }
    }
  }
  void Handle(int num, int sock, unordered_map<int, Data<std::string> *> &map, epoll_event *eveptr)
  {
    for (ssize_t i = 0; i < num; i++)
    {
      if (eveptr[i].events & EPOLLIN)
        Recv(eveptr[i].data.fd, map, sock);
      if (eveptr[i].events & EPOLLOUT)
        Write(eveptr[i].data.fd, map);
    }
  }
  ~Funtion()
  {
  }

private:
  void Add(unordered_map<int, Data<std::string>  *>::iterator cur, unordered_map<int, Data<std::string>  *> &map)
  {
    Data<std::string>  *ptr = new Data<std::string> ;
    ptr->_epfd = cur->second->_epfd;
    ptr->_eptr = cur->second->_eptr;
    ptr->_sock = cur->second->_sock;
    ptr->_ptr = &_pool;
    int sock = cur->second->_sock->Accept();
    ptr->_fd = sock;
    ptr->_eptr->Epoll_ctl(EPOLL_CTL_ADD, sock, EPOLLIN | EPOLLET);
    int fl = fcntl(sock, F_GETFL);
    if (fl < 0)
      cout << "fcntl fail: " << strerror(errno) << endl;
    fcntl(sock, F_SETFL, fl | O_NONBLOCK);
    map.emplace(make_pair(sock, ptr));
  }

private:
  PthreadPool<std::string> _pool;
};
